package com.biggabrotha {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.TimerEvent;
	import flash.media.Video;
	import flash.net.registerClassAlias;
	import flash.utils.Timer;
	import flash.utils.getQualifiedClassName;

	import mx.containers.Canvas;
	import mx.containers.TitleWindow;
	import mx.controls.HSlider;
	import mx.effects.AnimateProperty;
	import mx.effects.Effect;

	public class BiggaBrothaClass extends Canvas implements IConfigurable {
		public var activePP:PictureProvider

		public function get activePPbyClassName():String {
			return getQualifiedClassName(activePP)

		}

		public function set activePPbyClassName(classname) {
			for (var i=0; i < knownPicutrePRoviders.length; i++) {
				var pp=knownPicutrePRoviders[i]
				if (pp) {
					var ppcn:String=getQualifiedClassName(pp)
					if (classname == ppcn) {
						switchToPP(pp)
						break;
					}

				}
			}
			trace("Class " + className + " is not a known PictureProvider. Leaving activePP untouched.")
		}

		public function get propertiesToConfigure():Array {
			return ["maxSnapshotInterval",
				"lineThickness",
				"thedurationx",
				"fadeTime",
				"animator",
				"activePPbyClassName",
				"mocFrameRate"]
		}

		public function BiggaBrothaClass() {
			super();
		}
		import mx.core.Container;
		import mx.core.IUIComponent;
		import mx.effects.easing.Linear;
		import mx.binding.utils.BindingUtils;
		import mx.collections.ArrayCollection;
		import mx.controls.Alert;
		import mx.events.EffectEvent;
		import mx.events.FlexEvent;
		import mx.events.ResizeEvent;
		import mx.events.TweenEvent;
//dont use bindable when drawing often
		private var _thex:Number;
		private var _they:Number;

//from mxml
///////////
		public var vline:Canvas
		public var hline:Canvas;
		[Bindable]
		public var maxSnapshotInterval:Number;
		[Bindable]
		public var lineThickness:Number;
		[Bindable]
		public var maxSnapshotIntervalGUI:HSlider;
		[Bindable]
		public var lineThicknessGUI:HSlider
		public var placeholder:DummyPictureProviderEmbedded
		public var configPanel:TitleWindow
		public var animate:Effect
		public var zuum:Effect
		public var fade:AnimateProperty
		public var shots:Canvas
		public var animatex:AnimateProperty
		public var animatey:AnimateProperty

		//no more bindings
		public function set thex(x:Number) {
			_thex=x
			vline.x=x - lineThickness
			activePP.x=x
//			trace(_thex)
		}

		public function get thex() {
			return _thex
		}

		public function set they(y:Number) {
			_they=y
			hline.y=y - lineThickness
			activePP.y=y
//			trace(_they)
		}

		public function get they() {
			return _they
		}

		public function moveDelta(d:Number) {
			_thex+=d
			_they-=d

			if (_thex > thewidth)
				_thex=-leaderLeft
			else if (_thex < leaderLeft)
				_thex=thewidth

			if (_they > theheight)
				_they=-leaderTop
			else if (_they < -leaderTop)
				_they=theheight

			vline.x=_thex - lineThickness
			activePP.x=_thex
			hline.y=_they - lineThickness
			activePP.y=_they
		}




		public function set mocFrameRate(fps:Number) {
			systemManager.stage.frameRate=fps
		}

		public function get mocFrameRate():Number {
			var fps=systemManager.stage.frameRate
			return fps
		}


		[Bindable]
		public var thewidth:int=0;
		[Transient]
		[Bindable]
		public var theheight:int=0;
		[Bindable]
		public var thedurationx:Number;
		[Bindable]
		public var leaderLeft:int=0; //135;
		[Bindable]
		public var leaderTop:int=0; //135;
		public var timer:Timer=new Timer(100, 0);
		protected static const dropTimer:Timer=new Timer(Number.MAX_VALUE, 0);
		private const dppe:DummyPictureProviderEmbedded=new DummyPictureProviderEmbedded()
		private const dummyPictureProviderNetwork:DummyPictureProviderNetwork=new DummyPictureProviderNetwork()
		private const googlePictureProvider:GooglePictureProvider //=new GooglePictureProvider()
		private const camPictureProvider:CamPictureProvider=new CamPictureProvider()
		private var snapshotsList:ArrayCollection=new ArrayCollection()
		private var knownPicutrePRoviders:Array=[dppe, dummyPictureProviderNetwork, googlePictureProvider, camPictureProvider]
//		public var me:BiggaBrotha;
		private var vid:Video
		private var paintDots:Boolean=false;
		[Bindable]
		public var fadeTime:Number=5000;

		protected function calculateNewDropTimerDuration(maxInterval:Number=NaN) {
			var newMaxInterval:Number=maxInterval ? maxInterval : maxSnapshotInterval
			var newDelay:Number=Math.round(Math.random() * newMaxInterval) + 1
			dropTimer.delay=newDelay
		}

		private var _animator:String="FLEX_ANIMATOR"

		public function set animator(a:String) {
			_animator=a
			selectAnimator()
		}

		public function get animator():String {
			return _animator
		}

		public static const FLEX_ANIMATOR="FLEX_ANIMATOR"
		public static const STRAIGHT_ANIMATOR="STRAIGHT_ANIMATOR"

		protected function selectAnimator() {

			if (_animator == FLEX_ANIMATOR)
				animate.play()
//				animate.resume()
			else
				animate.stop()
//				animate.pause()

			if (_animator == STRAIGHT_ANIMATOR) {
				thex=Math.round(thex)
				they=Math.round(they)
				addEventListener(Event.ENTER_FRAME, straightAnimatorsEnterFrame)
			} else
				removeEventListener(Event.ENTER_FRAME, straightAnimatorsEnterFrame)
		}

		private function straightAnimatorsEnterFrame(e:Event) {
			moveDelta(1)
		}

		protected function hotkeyHandler(event:KeyboardEvent) {
			//jesus... how to handle that meSS?
			var keyCode:uint=event.keyCode
			switch (keyCode) {
				case 112:
					trace("F1?")
					if (!zuum.isPlaying) {
						if (configPanel.alpha > 0) {
							//save 
							MinistryOfConfiguration.save(this)


							//and close
							zuum.play([configPanel], true)
//							configPanel.visible=false
						} else {
							//open (and load?)
							configPanel.alpha=1
							configPanel.visible=true
							zuum.play([configPanel])
						}
					}
//            PopUpManager.addPopUp(configPanel, this, true)
					return;
			}
			var key:String=String.fromCharCode(event.charCode).toLowerCase();
			switch (key) {
				case "a":
					Alert.show("a");
					break;
				case "c":
					switchToPP(camPictureProvider);
					break;
				case "d":
					this.paintDots=!this.paintDots;
					break;
				case "e":
					switchToPP(dppe);
					break;
				case "f":
					animator=FLEX_ANIMATOR;
					break;
				case "n":
					switchToPP(dummyPictureProviderNetwork);
					break;
				case "s":
					animator=STRAIGHT_ANIMATOR;
					break;
				case "z":
					//testing
					currentState="config";
					break;

				case "r1":
					// Do something with the one which is not on the keypad.
					break;
				case "n.":
					// Do something with the number pad's period.
					break;
				default:
					Alert.show("unknown command: " + key + "/" + keyCode);
			}
		}

		protected function dropTimerListener(e:TimerEvent) {
			calculateNewDropTimerDuration()

			//goto bitmapasset
			var b:Bitmap=takeSnapshot()
			b.x=_thex
			b.y=_they
//				trace("pixelSnapping: " + b.pixelSnapping)
			shots.rawChildren.addChild(b)
			fade.play([b])
			if (paintDots) {
				var s:Sprite=new Sprite()
				s.graphics.beginFill(0xFFFFFF, 1)
				s.graphics.drawCircle(-1, -1, 3)
				s.graphics.endFill()
				s.x=_thex
				s.y=_they
				shots.rawChildren.addChild(s)
			}
		}

		public function takeSnapshot():Bitmap {
			var snapshot:BitmapData=new BitmapData(activePP.width, activePP.height, true);
			//and the object better be in the disply list
			snapshot.draw(activePP);
			var snapshotbitmap:Bitmap=new Bitmap(snapshot);
			snapshotbitmap.cacheAsBitmap=true
			return snapshotbitmap;
		}

		override public function toString():String {
			return "x/y:" + thex + "/" + they + " w/h:" + thewidth + "/" + theheight + " AR:" + (thewidth / theheight)
		}

		protected function resizeHandler(event:ResizeEvent=null) {
			//databinding is not reliable in Effects, so set everything from here
			thewidth=width
			theheight=height
			animatex.fromValue=-leaderLeft
			animatex.toValue=thewidth
			animatey.fromValue=theheight
			animatey.toValue=-leaderTop
			recalculateDuration()
		}

		function recalculateDuration() {
			animatex.duration=thedurationx
			animatey.duration=thedurationx / (thewidth / theheight)
			if (animate.isPlaying) {
				animate.stop()
				animate.play()
			}
		}

		private function switchToPP(pp:PictureProvider) {
			if (pp == null) {
				Alert.show("switch to null?")
				return
			}
			if (activePP != pp) {
				replaceChild(DisplayObject(activePP), DisplayObject(pp), this)
				activePP=pp
			}
		}

		public function replaceChild(oldChild:DisplayObject, newChild:DisplayObject, parentComponent:Container) {
			var oldIndex=parentComponent.getChildIndex(oldChild)
			parentComponent.removeChild(oldChild)
			parentComponent.addChildAt(newChild, oldIndex)
		}

		protected function preinitializeHandler(event:FlexEvent):void {
			//find good PP for startup and make sure it gets added
			//activePP = camPictureProvider
			//switch
			registerClassAlias(this.className, BiggaBrotha)
		}

		protected function fade_effectEndHandler(event:EffectEvent):void {
			var bm:Bitmap=event.effectInstance.target as Bitmap
			if (bm == null)
				return;
			if (shots.rawChildren.contains(bm))
				shots.rawChildren.removeChild(bm)
		}


	}
}